import time
from datetime import datetime, timedelta

import schedule
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models import DayAheadPlan, DayAheadPlanResource, IntraDayTaskResource
from app.utils.resource import send2resource
from common.database import get_db
from common.log import get_logger
from common.time import get_datetime_now, get_date_today, combine_date_time

logger = get_logger('scheduler')


def run_ahead_job(db: Session, plan: DayAheadPlanResource, start_time: str, end_time: str):
    """
    执行日前任务
    """
    send_payload = {
        "resourceId": plan.resource_id,
        "targetPower": float(plan.value),
        "startTime": start_time,
        "endTime": end_time,
    }
    logger.info(f"now_time: {start_time}")
    logger.info(f"fifteen_time: {end_time}")
    logger.info(f"run_job: {send_payload}")
    send2resource(db, plan.resource_id, send_payload)


def run_intra_job(db, today_intra_day_task: IntraDayTaskResource):
    """
    执行紧急任务
    """
    send_payload = {
        "resourceId": today_intra_day_task.resource_id,
        "targetPower": float(today_intra_day_task.target_power),
        "startTime": today_intra_day_task.start_time.strftime("%Y-%m-%d %H:%M:%S"),
        "endTime": today_intra_day_task.end_time.strftime("%Y-%m-%d %H:%M:%S"),
    }
    send2resource(db, today_intra_day_task.resource_id, send_payload)


def detect_intra_job(db: Session):
    """
    检测紧急任务
    """
    datetime_now = get_datetime_now()
    logger.info(f"start detect day intra job - {datetime_now}")
    today_intra_day_tasks = db.scalars(select(IntraDayTaskResource).filter_by(handle_status=0)).all()
    if today_intra_day_tasks is not None:
        for today_intra_day_task in today_intra_day_tasks:
            start_time = today_intra_day_task.start_time.strftime("%Y-%m-%d %H:%M:%S")
            end_time = today_intra_day_task.end_time.strftime("%Y-%m-%d %H:%M:%S")
            if start_time <= datetime_now <= end_time:
                run_intra_job(db, today_intra_day_task)
                today_intra_day_task.handle_status = 1
        db.commit()
    else:
        logger.info(f"no intra plan - {datetime_now}")
        return


def detect_ahead_job(db):
    """
    检测日前任务
    """
    datetime_now = get_datetime_now()
    today_time = get_date_today()
    logger.info(f"start detect day ahead job - {datetime_now}")
    today_plan = db.scalars(select(DayAheadPlan).filter_by(plan_time=today_time)).first()
    if today_plan is None:
        logger.info(f"no plan - {datetime_now}")
        return
    now_plans = db.scalars(
        select(DayAheadPlanResource).filter_by(invitation_id=today_plan.invitation_id, handle_status=0)).all()
    if now_plans is None:
        logger.info(f"no plan - {datetime_now}")
        return
    for now_plan in now_plans:
        now_plan_key_datetime = datetime.strptime(now_plan.key, "%H:%M")
        fifteen_minutes_before = now_plan_key_datetime - timedelta(minutes=15)
        fifteen_datetime = (combine_date_time(today_time, fifteen_minutes_before.strftime("%H:%M")).
                            strftime("%Y-%m-%d %H:%M:%S"))
        key_datetime = combine_date_time(today_time, now_plan.key).strftime("%Y-%m-%d %H:%M:%S")
        if fifteen_datetime <= datetime_now <= key_datetime:
            run_ahead_job(db, now_plan, datetime_now, now_plan.key)
            now_plan.handle_status = 1
    db.commit()


def detect_job(db: Session):
    detect_intra_job(db)
    detect_ahead_job(db)


def scheduler(db: Session):
    detect_job(db)
    schedule.every(10).seconds.do(detect_job, db)  # 每分钟执行一次数据库检测任务


def start():
    db = next(get_db())
    scheduler(db)
    while True:
        schedule.run_pending()
        time.sleep(1)


if __name__ == '__main__':
    start()
